package com.to8to.scene.compute;

import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.thrift.TFieldIdEnum;
import org.apache.thrift.meta_data.FieldMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.QueryOperators;
import com.to8to.commons.mongo.DBParam;
import com.to8to.commons.mongo.MongoClientBase;
import com.to8to.commons.utils.Progress;
import com.to8to.scene.server.Commons;
import com.to8to.scene.server.Tables;
import com.to8to.thrift.diary.module.TComment;
import com.to8to.thrift.diary.module.TDiary;
import com.to8to.thrift.diary.module.TProduct;
import com.to8to.thrift.diary.module.TScene;

/**
 * DataDiffComputer.java
 * 作 者:alpha.ren
 * 版 本:v2.0
 * 日期:2014年12月6日
 * 描 述:统计数据修复的变化，以帮助恢复
 */
public class DataDiffComputer
{
    public static Logger logger = LoggerFactory.getLogger(DataDiffComputer.class);

    static MongoClientBase mongo_main = null;
    static MongoClientBase mongo_ref = null;

    public static void main(String[] args) throws ConfigurationException, FileNotFoundException
    {
        Commons.init(null);

        mongo_main = Commons.mongo;

        PropertiesConfiguration pc = new PropertiesConfiguration("common.properties");

        String dbhost = pc.getString("mongodb_ref.host");
        String dbuser = pc.getString("mongodb_ref.user");
        String dbpassword = pc.getString("mongodb_ref.password");
        String dbdatabase = pc.getString("mongodb_ref.database");

        DBParam param = new DBParam(dbhost, dbuser, dbpassword, dbdatabase);

        mongo_ref = new MongoClientBase(param);

        logger.info("connect to mongo_ref:{}/{}/", dbhost, dbdatabase);

        List<String> arg_list = Arrays.asList(args);

        //        arg_list = Arrays.asList(new String[] { Tables.Scene, Tables.Diary, Tables.Comment, Tables.Product });
        arg_list = Arrays.asList(new String[] { Tables.StaticConfigValue, Tables.Diary });

        if (arg_list.contains(Tables.Scene))
            compare(mongo_main, mongo_ref, Tables.Scene);
        if (arg_list.contains(Tables.Diary))
            compare(mongo_main, mongo_ref, Tables.Diary);
        if (arg_list.contains(Tables.Comment))
            compare(mongo_main, mongo_ref, Tables.Comment);
        if (arg_list.contains(Tables.Product))
            compare(mongo_main, mongo_ref, Tables.Product);
        if (arg_list.contains(Tables.StaticConfigValue))
            compare(mongo_main, mongo_ref, Tables.StaticConfigValue);

        System.out.println("hahha");
        System.exit(0);
    }

    private static void compare(MongoClientBase mongo_new, MongoClientBase mongo_old, String table)
    {
        logger.info("compare table:{}", table);
        Progress progress = new Progress(mongo_old.count(table));
        Iterable<String> ids =
            mongo_old.ids(table, new BasicDBObject("ctime", new BasicDBObject(QueryOperators.GT, 0)), new BasicDBObject("ctime", -1));

        Map<? extends TFieldIdEnum, FieldMetaData> meta_data_map = null;
        switch (table)
        {
        case "scene":
        {
            meta_data_map = TScene.metaDataMap;
            break;
        }
        case "diary":
        {
            meta_data_map = TDiary.metaDataMap;
            break;
        }
        case "comment":
        {
            meta_data_map = TComment.metaDataMap;
            break;
        }
        case "product":
        {
            meta_data_map = TProduct.metaDataMap;
            break;
        }
        }

        for (String id : ids)
        {
            logger.trace("scanning:{}", id);
            progress.increase(logger);
            DBObject record_new = mongo_new.findById(table, id);
            DBObject record_old = mongo_old.findById(table, id);

            if ((null != record_new) && !record_new.equals(record_old))
            {
                //                <TBase<?,?>, TFieldIdEnum>
                for (TFieldIdEnum field : meta_data_map.keySet())
                {
                    if (null == record_old.get(field.getFieldName()) && null == record_new.get(field.getFieldName()))
                        continue;
                    if ((null == record_old.get(field.getFieldName()) && null != record_new.get(field.getFieldName()))
                        || (null != record_old.get(field.getFieldName()) && null == record_new.get(field.getFieldName()))
                        || (!record_old.get(field.getFieldName()).equals(record_new.get(field.getFieldName()))))
                    {
                        logger.warn("{} diff on {} : record_new - {} ==== record_old - {}", id, field.getFieldName(), record_new.get(field.getFieldName()), record_old.get(field.getFieldName()));
                    }
                }
            }
        }
    }
}
